人员雇佣
Time Limit: 20 Sec Memory Limit: 259 MB
Description
作为一个富有经营头脑的富翁,小L决定从本国最优秀的经理中雇佣一些来经营自己的公司。这些经理相互之间合作有一个贡献指数,(我们用Ei,j表示i经理对j经理的了解程度),即当经理i和经理j同时被雇佣时,经理i会对经理j做出贡献,使得所赚得的利润增加Ei,j。当然,雇佣每一个经理都需要花费一定的金钱Ai,对于一些经理可能他做出的贡献不值得他的花费,那么作为一个聪明的人,小L当然不会雇佣他。 然而,那些没有被雇佣的人会被竞争对手所雇佣,这个时候那些人会对你雇佣的经理的工作造成影响,使得所赚得的利润减少Ei,j(注意:这里的Ei,j与上面的Ei,j 是同一个)。 作为一个效率优先的人,小L想雇佣一些人使得净利润最大。你可以帮助小L解决这个问题吗?
第一行有一个整数N<=1000表示经理的个数 第二行有N个整数Ai表示雇佣每个经理需要花费的金钱 接下来的N行中一行包含N个数,表示Ei,j,即经理i对经理j的了解程度。(输入满足Ei,j=Ej,i)
Output
第一行包含一个整数,即所求出的最大值。
3
3 5 100
0 6 1
6 0 2
1 2 0
Sample Output
1
HINT
20%的数据中 N<=10
50%的数据中 N<=100
100%的数据中 N<=1000 , Ei,j<=maxlongint , Ai<=maxlongint
Main idea
给定若干关系,选择一个人需要固定的费用,对于i,j,选择了其中一个则损失E[i][j],两个都选了则获得2*E[i][j],问能获得的最大价值。
Solution
显然就是一个最小割的模型,我们直接套用论文里面的模型即可。
针对于这道题,我们对于代价建图,用Ans=总和-最小代价即可。
对于第i个点,如果选了,会损失a[i],连边**(S,i,a[i]):表示选了它之后的代价;如果不选,会损失ΣE[i][j],所以连边(i,T,ΣE[i][j])**,表示不选的损失。
然后对于一对点i,j,连边**(i,j,2*E[i][j])**,表示如果不选i,选了j的话,本来i中选j的利益得不到,又要损失j对i的影响为E[i][j],一共损失了2*E[i][j]。
然后求一下最小割即可。
Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97
| #include<bits/stdc++.h> using namespace std;
typedef long long s64; const int ONE=5000005; const s64 INF=21474836400000;
int n,x; s64 res; int tou,wei,S,T; int Dep[ONE],q[1000001],E[ONE]; int next[ONE],first[ONE],go[ONE],tot; s64 w[ONE]; s64 Ans;
int get() { int res=1,Q=1;char c; while( (c=getchar())<48 || c>57 ) if(c=='-')Q=-1; res=c-48; while( (c=getchar())>=48 && c<=57 ) res=res*10+c-48; return res*Q; }
int Add(int u,int v,s64 z) { next[++tot]=first[u]; first[u]=tot; go[tot]=v; w[tot]=z; next[++tot]=first[v]; first[v]=tot; go[tot]=u; w[tot]=0; }
int Bfs() { memset(Dep,0,sizeof(Dep)); tou=0; wei=1; q[1]=S; Dep[S]=1; for(int i=S;i<=T;i++) E[i]=first[i]; while(tou<wei) { int u=q[++tou]; for(int e=first[u];e;e=next[e]) { int v=go[e]; if(Dep[v] || !w[e]) continue; Dep[v]=Dep[u]+1; q[++wei]=v; } } return (Dep[T]>0); }
s64 Dfs(int u,s64 Limit) { if(u==T || !Limit) return Limit; s64 from=0,f; for(int &e=E[u];e;e=next[e]) { int v=go[e]; if(Dep[v]!=Dep[u]+1 || !w[e]) continue; f=Dfs(v,min(Limit,w[e])); w[e]-=f; w[((e-1)^1)+1]+=f; Limit-=f; from+=f; if(!Limit) break; } return from; }
int main() { n=get(); S=0; T=n+1; for(int i=1;i<=n;i++) { x=get(); Add(S,i,x); }
for(int i=1;i<=n;i++) { res=0; for(int j=1;j<=n;j++) { x=get(); res+=x; Ans+=x; Add(i,j,2*x); } Add(i,T,res); }
while(Bfs()) Ans-=Dfs(S,INF);
printf("%lld",Ans);
}
|